package com.twu.biblioteca;

import java.io.IOException;
import java.util.*;

public class BibliotecaApp {

    private UserAccount loggedInUser;
    private Library library = new Library();
    private Map<String, UserAccount> users = new HashMap<String, UserAccount>();

    public static void main(String[] args) {
        BibliotecaApp app = new BibliotecaApp();
        app.startApp();
    }

    public BibliotecaApp() {
        UserAccount userAccount = new UserAccount("283-5943", "pas$w0rd", "John Doe", "john.doe@email.com", "+61451111111");
        users.put(userAccount.getLibraryNumber(), userAccount);

        Random randomGenerator = new Random();
        for(int i = 0; i < 5; i++) {
            library.addToLibrary(new Book("Book" + i));

            int ratingValue = randomGenerator.nextInt(12);
            String rating = (ratingValue == 11 || ratingValue == 0) ? "Unrated" : String.valueOf(ratingValue);

            Movie movie = new Movie("Movie" + i, 2012, "Steve Harding",rating);
            library.addToLibrary(movie);
        }
    }

    public void startApp() {
        int option;

        printText(displayWelcome() +
                "Available Library Books\n"
                + "-------------------------\n"
                + listAvailableItems(LibraryItemType.Book));

        do {
            printText("\n\nMAIN MENU\n"
                    + "============");

            for(String o : getMenuOptions())
                printText(o);

            printText("Choose an option ==> ");
            option = Integer.parseInt(getUserInput(int.class, "Select a valid option!"));
            printText(selectOption(option));
        } while (option != 0);
    }

    public String displayWelcome() {
        return "Welcome to Biblioteca!\n" +
            "==========================\n\n";
    }

    public String[] getMenuOptions() {
        if(loggedInUser != null) {
            return new String[]{ "1 - List Items in Library", "2 - Checkout Item", "3 - Return Item",
                    "4 - Account Information", "0 - Exit" };
        } else {
            return new String[]{ "1 - List Items in Library", "2 - Checkout Item", "3 - Return Item",
                    "0 - Exit" };
        }
    }

    public String selectOption(int option) {
        LibraryItemType type;

        switch (option) {
            case 0: return "";
            case 1:
                type = selectItemType("Type of Items in Library");
                return listItems(type);
            case 2:
                type = selectItemType("Type of Item to Checkout");
                return checkoutItem(type);
            case 3:
                type = selectItemType("Type of Item to Return");
                return returnItem(type);
            case 4:
                if(loggedInUser != null)
                    return listUserAccountInfo();
                else
                    return "Select a valid option!";
            default: return "Select a valid option!";
        }
    }

    public String listItems(LibraryItemType type) {
        if(type != null) {
            clearScreen();
            return listAvailableItems(type);
        } else {
            return "";
        }
    }

    public String checkout(String title, LibraryItemType type, UserAccount user) {
        boolean result = library.checkoutFromLibrary(title, user);

        if(result)
            return "Thank you! Enjoy the " + type.toString().toLowerCase() + ".";
        else
            return "That " + type.toString().toLowerCase() + " is not available.";
    }

    public String returnItemToLibrary(String title, LibraryItemType type) {
        boolean result = library.returnToLibrary(title);

        if(result)
            return "Thank you for returning the " + type.toString().toLowerCase() + ".";
        else
            return "That is not a valid " + type.toString().toLowerCase() + " to return.";
    }

    public boolean loginToBiblioteca(String libraryNumber, String password) {
        if(users.containsKey(libraryNumber)) {
            if(users.get(libraryNumber).getPassword().equals(password)) {
                this.loggedInUser = users.get(libraryNumber);
                return true;
            }
        } else {
            return false;
        }

        return false;
    }

    public String listUserAccountInfo() {
        clearScreen();
        String output = "Account Information\n";
        output += "-------------------------------------------\n";

        if(loggedInUser != null) {
            output += "Name: \t\t\t\t\t" + loggedInUser.getName() + "\n";
            output += "Email: \t\t\t\t\t" + loggedInUser.getEmailAddress() + "\n";
            output += "Phone Number: \t\t\t" + loggedInUser.getPhoneNumber() + "\n";
        }

        return output;
    }

    public UserAccount getItemHolder(String name) {
        LibraryItem item = library.findByTitle(name);
        return item.getItemHolder();
    }

    private void clearScreen() {
        try {
            Runtime.getRuntime().exec("clear");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private LibraryItemType selectItemType(String title) {
        printText("\n\n" + title + "\n" +
                "----------------------------\n" +
                "1 - Books\n" +
                "2 - Movies\n" +
                "0 - Back\n\n"+
                "Choose an option ==> ");

        int option = Integer.parseInt(getUserInput(int.class, "Select a valid option!"));

        switch (option) {
            case 0: return null;
            case 1: return LibraryItemType.Book;
            case 2: return LibraryItemType.Movie;
        }

        return null;
    }

    private boolean getLoginDetails() {
        if(loggedInUser == null) {
            printText("Enter Library Number (###-####): ");
            String libraryNumber = getUserInput(String.class, null);
            printText("Enter password: ");
            String password = getUserInput(String.class, null);
            return loginToBiblioteca(libraryNumber, password);
        } else {
            return true;
        }
    }

    private void printText(String text) {
        System.out.print(text);
    }

    private String getUserInput(Class inputType, String invalidMessage) {
        String input = "";
        Scanner in = new Scanner(System.in);

        if(inputType == int.class) {
            if(in.hasNextInt()) {
                input = String.valueOf(in.nextInt());
            } else {
                System.out.println(invalidMessage);
            }
        } else {
            if(in.hasNext()) {
                input = in.next();
            }
        }

        return input;
    }

    private String listAvailableItems(LibraryItemType type) {
        String output;

        if(type == LibraryItemType.Movie) {
            output = "Name\t\t\t\t\t\t";
            output += "Year\t\t";
            output += "Director\t\t\t\t\t\t";
            output += "Rating\n";
            output += "====================================================================================\n";

            List<LibraryItem> availableMovies = library.getAvailableItems(type);
            for(LibraryItem m : availableMovies) {
                output += m.getName() + "\t\t\t\t\t\t";
                output += ((Movie)m).getYear() + "\t\t";
                output += ((Movie)m).getDirector() + "\t\t\t\t\t\t";
                output += ((Movie)m).getRating() + "\n";
            }
        } else {
            output = type.toString() + "s\n" +
            "=============\n";

            List<LibraryItem> availableItems = library.getAvailableItems(type);
            for(LibraryItem b : availableItems) {
                output += b.getName() + "\n";
            }
        }

        return output;
    }

    private String checkoutItem(LibraryItemType type) {
        String name;

        if(getLoginDetails()) {
            printText("Enter name of " + type.toString().toLowerCase() + " => ");
            name = getUserInput(String.class, null);
            return checkout(name, type, loggedInUser);
        } else {
            return "Invalid credentials!";
        }
    }

    private String returnItem(LibraryItemType type) {
        String name;

        if(getLoginDetails()) {
            printText("Enter name of " + type.toString().toLowerCase() + " => ");
            name = getUserInput(String.class, null);
            return returnItemToLibrary(name, type);
        } else {
            return "Invalid credentials!";
        }
    }
}
